This document describes Memory Monitor, a Virtual User 2.0 external tool which enables Virtual User script writers to get information about how memory is being utilized on a target Macintosh. Memory Monitor provides information from three different sources: the Process Manager, the Memory Manager, and Finder's "About This Macintosh" dialog. If you are not familiar with Virtual User external tools, please refer to the “Using External Tools” chapter in the Virtual User Language Reference manual.
In This Package
The set of files for this Memory Monitor package includes:
Memory Monitor Read Me - This file.
Memory Monitor - The application which performs the services.
MemoryMonitor.vu - A Virtual User example script.
MemoryMonitor.vulib - A Virtual User task library which provides a task call interface.
Apple® Event Manager 1.0.1 - Bug fix extension for AppleEvents.
Memory Monitor Requirements
Hardware Requirements :
Memory Monitor runs on all Macintosh models including and after the Macintosh Plus.
Software Requirements :
Memory Monitor requires System Software 7.0 or greater, and Apple® Event Manager v1.0.1 or later. Memory Monitor requires Virtual User 2.0 or greater.
Installation
To install Memory Monitor on the Target:
Step 1: Copy the Memory Monitor application to a disk connected to the machine.
The location of the application is not important to Virtual User.
Step 2: Copy the Apple® Event Manager extension to the machine’s Extensions Folder.
( In the future this extension may become obsolete, i.e. rolled into System Software ).
To install MemoryMonitor .vulib on the Host:
Step 1: On the host, drag the file “MemoryMonitor.vulib” to the same folder containing your other Virtual User libraries.
General Memory Monitor Information
The "MemoryMonitor.vulib" script library provides a task level interface for accessing the services provided by Memory Monitor. Script writers should use these tasks, rather than calling Memory Monitor directly, in order to localize all calls to Memory Monitor. In this way, if changes are ever made to the service level interface, the task level interface can remain the same, and required changes are isolated to one file.
Each task in the library returns a list of four elements: Error Code, Result, Error Message, Script Error Code. The first three elements, Error Code, Result, and Error Message, are the same as those returned from any external tool call ( see "Virtual User Language Reference" ). The fourth element, Script Error, is the value obtained from calling the built-in task ScriptError just after the tool call is made. In this way all information pertaining to the tool call is returned to the script.
Several of the tasks either take as arguments or return numeric values which are larger than Virtual User supports ( supported range : -32768 … 32767 ). To get around this problem, all numeric values returned by Memory Monitor, which fall outside the supported range, are returned as numeric strings. The number 131072 would be returned as the string: '131072'. Numeric strings can be converted to regular numbers using the built-in task StrToNum(). If the number is too large to be converted, StrToNum() will return undefined. You can still perform arithmetic operations or comparisons on these numeric strings, though, by using the MathTool, another external tool supplied with Virtual User. (See the ReadMe documentation for the MathTool for more information.)
Most tasks in the library take a boolean parameter called pCallAsync. This parameter determines if V.U. makes the tool call synchronously or asynchronously. If the call is made synchronously, the next statement of the V.U. script is not executed until the tool has completed it's operation and has returned a result. If the call is made asynchronously, script execution continues without waiting for the tool to complete its operation. The script must later "Poll" for the results. For a more thorough explanation see the Virtual User Language Reference. This parameter has a default value of false ( synchronous calls ), so if it is not specified in the parameter list a synchronous call is made.
MemoryMonitor.vulib Tasks
InitMemoryMonitor
Description
InitMemoryMonitor task must be called before any other tasks within MemoryMonitor.vulib. It starts up Memory Monitor and makes it available to Virtual User.
Syntax
Task InitMemoryMonitor( LaunchOnTarget := false )
Input
The LaunchOnTarget is a Boolean parameter which determines whether Memory Monitor is launched on the target or the host. It is expected that most script writers will want to use Memory Monitor on the target, in which case they will pass a true expression.
Output
The returned Result is not defined. In general it will be equal to the 'undefined' V.U. symbol.
Diagnostics
Any errors encountered are reported through Error Code, Error Message, and/or Script Error Code.
Example
Script Statements
x := InitMemoryMonitor( true ); # Launch Memory Monitor on the target
Println x;
Output ( reformatted with comments )
{ 0, # Error Code = 0, no error occured
undefined, # Result , no additional info to return
undefined, # Error Message , no error message
0 # Script Error, no script error occured
}
QuitMemoryMonitor
Description
QuitMemoryMonitor causes the Memory Monitor application to quit, and V.U. to no longer recognize Memory Monitor as an available external tool. If you call QuitMemoryMonitor ( say to free memory for other applications ), you must call InitMemoryMonitor again, before calling other MemoryMonitor.vulib tasks.
Syntax
Task QuitMemoryMonitor( )
Input
There are no input parameters.
Output
The returned Result is not defined. In general it will be equal to the 'undefined' V.U. symbol.
Diagnostics
Any errors encountered are reported through Error Code, Error Message, and/or Script Error Code.
Example
Script Statements
x := QuitMemoryMonitor(); # Quit the Memory Monitor application
Println x;
Output ( reformatted with comments )
{ 0, # Error Code = 0, no error occured
undefined, # Result , no additional info to return
undefined, # Error Message , no error message
0 # Script Error, no script error occured
}
GetAllProcesses
Description
This task returns information about each Process Manager process. The information includes the following: name, type, signature, partition size, partition location in memory, free bytes within the partition, and the path name of the application.
Syntax
Task GetAllProcesses( CallAsync )…
Input
There are no input parameters for this task.
Output
The returned Result is a list containing one element for each process. Each element is a list that contains the following items:
Index Data Type Data Comments
1 string Name The process’ name
2 string Type The type of the process
3 string Signature The signature of the process
4 string Size in bytes Decimal digits of the size of the process’ partition
5 string Location Decimal digits of the starting address of the process’ partition
6 string Free bytes Decimal digits of the Free bytes in the process’ partition
7 string Pathname Full path name for the file from which the process originated
Diagnostics
Any errors encountered are reported through Error Code, Error Message, and/or Script Error Code.
Example
Script Statements
ProcList := GetAllProcesses();
Println ProcList;
Output ( reformatted with comments )
{ 0, # call completed without errors
{ # the list containing each process’ information
{
'Finder', # Process Name
'APPL', # Type
'MACS', # Signature
'253664', # Size
'7436740', # Location
'5236', # Free Memory
'HD:System Folder:Finder' # Free Memory
},
... # More Processes, if existent
},
undefined, 0
}
GetProcessInfo
Description
This task returns information about a specific Process Manager process. The information includes the following: name, type, signature, partition size, partition location in memory, free bytes within the partition, and the pathname to the application. This task is essentially the same as GetAllProcesses, but it returns information pertaining to only the specified process.
Syntax
Task GetProcessInfo( procName, CallAsync )…
Input
The procName parameter is the name of the process for which information is to be gathered.
Output
The returned Result is a list and contains the following items:
Index Data Type Data Comments
1 string Name The process’ name
2 string Type The type of the process
3 string Signature The signature of the process
4 string Size in bytes Decimal digits of the size of the process’ partition
5 string Location Decimal digits of the starting address of the process’ partition
6 string Free bytes Decimal digits of the Free bytes in the process’ partition
7 string Pathname Full path name for the file from which the process originated
Diagnostics
Any errors encountered are reported through Error Code, Error Message, and/or Script Error Code.
Example
Script Statements
ProcInfo := GetProcessesInfo( 'Finder' );
Println ProcInfo;
Output ( reformatted with comments )
{ 0, # call completed without errors
{
'Finder', # Process Name
'APPL', # Type
'MACS', # Signature
'253664', # Size
'7436740', # Location
'5236', # Free Memory
'HD:System Folder:Finder' # Free Memory
},
undefined, # no error message
0 # no script error occurred
}
GetZoneTotals
Description
This task returns a summary of how memory is being utilized within a specific heap zone. There are three major categories: Free blocks, Nonrelocatable blocks, and Relocatable blocks. The third category is further broken down into two minor categories: Locked Relocatable and Purgable & Unlocked Relocatable. For each category the number of blocks allocated and the total bytes which they occupy is reported.
The ZoneSelector parameter determines which heap zone is examined. There are two forms, one for top level heap zones, and one for nested heap zones.
Form 1: This is the simplest form, consisting of a single string. The string contains the name of a Process Manager process. The heap zone belonging to that process is examined. Example: 'Finder' - the Finder's heap zone.
Form 2: This is the more complex form, consisting of a list whose first item is a process name ( like form 1 ) and following items are integers. The string contains a Process Manager process name. The following integers are interpreted as indecies for the nested heap zones. The indecies are assigned according to the order within the memory address space. Example: { 'Memory Monitor', 2 } - the second nested zone within Memory Monitor's heap zone.
Two special names have been defined for the heap zones which don't belong to a Process Manager process, that is the System heap zone and the MultiFinder (or Process Manager ) heap zone. The two names are 'SystemZone' and 'MultiFinderZone'. These names may be used in place of a process name in either forms above.
Example { 'SystemZone', 2, 1 } - the first nested heap zone within the second nested heap zone within the System heap zone.
Output
The returned Result is a list of six elements which contain the number of blocks and the total bytes within those blocks for each of the five categories ( Free, Nonrelocatable, Relocatable, Locked Relocatable, Purgable Relocatable) and the over all total. The list looks like this:
Index Data Type Data Comments
1 list Free Free space
2 list Nonrelocatable Nonrelocatable space
3 list Relocatable Relocatable space
4 list Locked Locked Relocatable space
5 list Unlocked & Purgable Unlocked & Purgable Relocatable
6 list Total Over all
Each of the six elements contains a list of two numbers: the number of blocks in that category, and the total number of bytes occupied by those blocks. The list looks like this:
Index Data Type Data Comments
1 number Block Count The number of blocks
2 string Byte Count Decimal digits of the byte count
Diagnostics
Any errors encountered are reported through Error Code, Error Message, and/or Script Error Code.
The ZoneSelector parameter is the same that is used by GetZoneTotals. Please refer to the Input section under GetZoneTotals for more information. The CallAsync parameter determines if the call is made asynchronously or synchronously.
Output
The returned Result is a list containing one element for each heap zone. Each element is a list and contains the following items:
Index Data Type Data Comments
1 string Starting Address Decimal digits of the heap zone's starting address
2 string Ending Address Decimal digits of the heap zone's ending address
3 string Size in bytes Decimal digits of the heap zone's size in bytes
4 list List of nested zones A list containing information about any nested zones
if there are no nested zones, the list has zero elements.
Diagnostics
Any errors encountered are reported through Error Code, Error Message, and/or Script Error Code.
Example
Script Statements
ZoneList := GetZoneMap( 'SystemZone' );
Println ZoneList;
Output ( reformatted with comments )
{ 0, # call completed without errors
{ # First Non-nested zone (System Zone)
{ '8192','1294903','1286711', # Start, End, Size
{
{ '8632','9891','1259',{} }, # First nested zone
{ '520460','530699','10239',{} } # Second nested zone
}
}
},
undefined, # no error message
0 # no script error occurred
}
CheckZone
Description
This task simply scans the zone and reports if any corrupted Memory Manager data structures are detected. Not all types of data corruptions are detected, but those that are detected are reported. The task returns a true if no corruptions are found, and false if a corruption is detected.
The ZoneSelector parameter is the same that is used by GetZoneTotals. Please refer to the Input section under GetZoneTotals for more information. The CallAsync parameter determines if the call is made asynchronously or synchronously.
Output
The returned Result is a boolean value. True for no corruptions detected, False when a corruption is detected.
Diagnostics
Any errors encountered are reported through Error Code, Error Message, and/or Script Error Code.
Example
This example checks the System heap for memory corruptions
Script Statements
HeapCheckResult := CheckZone( 'SystemZone' );
Println HeapCheckResult;
Output ( reformatted with comments )
{ 0, true, undefined, 0 } # No errors, Heap is ok, no error message, no script error
GetAboutThisMacintosh
Description
This task returns information which is available to the user via the "About This Macintosh" dialog.
Syntax
Task GetAboutThisMacintosh( pCallAsync := false )
Input
The CallAsync parameter determines if the call is made asynchronously or synchronously.
Output
The returned Result is a list containing one element for each heap zone. Each element is a list and contains the following items:
Index Data Type Data Comments
1 string Physical Memory Decimal digits of the Physical memory in kilobytes
2 string Logical Memory Decimal digits of the Logical memory in kilobytes
3 string Largest Free Block Decimal digits of the largest free block in kilobytes
4 list List of application info A list containing information for each application
For each Application the following information is returned.
Index Data Type Data Comments
1 string Name The name of the application in bytes
2 string Memory usage Decimal digits of the application's partition size in bytes
Diagnostics
Any errors encountered are reported through Error Code, Error Message, and/or Script Error Code.
This task "Reads" bytes from the specified location in memory and returns them to the script. This task can be used to get "Raw" data from any location in memory.
The StartingAddress parameter is the address of the first byte to read. ByteCount indicates the number of bytes to read. CallAsync determines if the call is made asynchronously or synchronously.
Output
The task's result is a list of numbers, each representing one of the bytes read.
Diagnostics
Any errors encountered are reported through Error Code, Error Message, and/or Script Error Code.
Example
This example reads the low global containing the current application's name.
Script Statements
### Fetch the bytes of interest
AppName := ReadBytes( { 0, 2320 }, 32 );
### Convert the list of bytes to a character string
s := "";
for i := 2 to AppName[2][1] + 1
s := s + CodeToCharacter( AppName[2][i] );
### Print the string
Println "App Name = '", s, "'";
Output ( reformatted with comments )
App Name = 'Memory Monitor'
MacsBugCmd
Description
This task allows the script to execute Macsbug commands via the Macsbug command line. Make sure that Macsbug is installed before using this service.
Syntax
Task MacsbugCmd( CommandLine,
Label := "Memory Monitor",
RemainInMacsBug := false,
pCallAsync := false )
Input
The CommandLine parameter contains the command line to be executed by Macsbug. One or more commands can be given, but multiple commands must be separated by semi-colons.
The Label parameter specifies the message which will appear in the Macsbug display. The default value is 'Memory Monitor'.
The RemainInMacsbug parameter is provided in case the scriptor wants to remain in Macsbug. Passing a value of 'true' will prevent the appending of a "Go" command to the command line.
CallAsync determines if the call is made asynchronously or synchronously.
Output
The returned Result is true if executed successfully, otherwise it is undefined.
Diagnostics
Any errors encountered are reported through Error Code, Error Message, and/or Script Error Code.
Example
This example logs some info into a log file using Macsbug.